/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mindbox.mueblesalpes.negocio.producto;

import com.mindbox.mueblesalpes.negocio.entity.Mueble;
import com.mindbox.mueblesalpes.negocio.entity.MuebleInventario;
import com.mindbox.mueblesalpes.negocio.exception.TiendaException;
import com.mindbox.mueblesalpes.negocio.persistence.PersistenciaLocal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * EJB que ofrece los servicios relacionados con los productos
 * @author Catalina Soto Zuluaga
 */

@Stateless
@DeclareRoles({"Administrador", "Gerente"})
public class ProductoService implements IProductoService {

    @PersistenceContext
    private EntityManager em;
    @EJB
    PersistenciaLocal persistenciaService;

    /**
     * Constructor del Ejb producto Service
     */
    public ProductoService() {
    }

    /**
     * Método que consulta todos los muebles registrados en el sistema
     * @return List<Mueble> listaMuebles Lista de muebles registrados
     */
    public List<Mueble> consultarMuebles() {
        List<Mueble> listaMueblesTemp = null;
        List<Mueble> listaMuebles = new ArrayList<Mueble>();
        try {
            listaMueblesTemp = persistenciaService.findAll(Mueble.class);
            for (Mueble mueble : listaMueblesTemp) {
                listaMuebles.add((Mueble) mueble.clone());
            }
        } catch (Exception e) {
            throw new TiendaException("Se presentó un error en la consulta de los productos");
        }
        return listaMuebles;
    }

    /**
     * Méodo que consulta un mueble en el sistema
     * @param mueble Mueble con tres parámetros posibles de búsqueda
     *               referencia, nombre, tipoMueble
     * @return   Lista de muebles que cumplen con el filtro de búsqueda
     */
    public List<Mueble> consultarMueble(Mueble mueble) {
        List<Mueble> listaMuebles = null;
        HashMap<String, String> parameters = new HashMap<String, String>();
        HashMap<String, Enum> parametersEnum = new HashMap<String, Enum>();

        try {
            if (mueble.getReferencia() == null) {
                mueble.setReferencia("");
            }
            if (mueble.getNombre() == null) {
                mueble.setNombre("");
            }

            parameters.put("referencia", mueble.getReferencia());
            parameters.put("nombre", mueble.getNombre());
            parametersEnum.put("tipoMueble", mueble.getTipoMueble());

            listaMuebles = persistenciaService.findByFilterEnum("Mueble", parameters, parametersEnum);

        } catch (Exception e) {
            throw new TiendaException("Se presentó un error en la consulta del mueble");
        }
        return listaMuebles;
    }

    /**
     * Método que consulta el inventario de muebles en el sistema
     * @return List<MuebleInventario> Lista del inventario de muebles
     */
    public List<MuebleInventario> consultarInventarioProductos() {
        List<MuebleInventario> listaMueblesInventarioTemp = null;
        List<MuebleInventario> listaMueblesInventario = new ArrayList<MuebleInventario>();
        try {
            listaMueblesInventarioTemp = persistenciaService.findAll(MuebleInventario.class);
            for (MuebleInventario muebleInventario : listaMueblesInventarioTemp) {
                listaMueblesInventario.add(muebleInventario);
            }
        } catch (Exception e) {
            throw new TiendaException("Se presentó un error consultando el inventario de los productos");
        }
        return listaMueblesInventario;
    }

    /**
     * Método que permite eliminar un mueble en el sistema
     * @param mueble Mueble que se eliminará del sistema
     */
    @RolesAllowed({"Administrador"})
    public void eliminarProducto(Mueble mueble) {
        try {
            if (mueble != null) {
                persistenciaService.delete(mueble);
            }
        } catch (Exception e) {
            throw new TiendaException("Se presentó un error eliminando el mueble");
        }
    }

    /**
     * Método que permite eliminar el inventario de un mueble en el sistema
     * @param muebleInventario Inventario que se eliminará del sistema
     */
    public void eliminarProductoInventario(MuebleInventario muebleInventario) {
        try {
            if (muebleInventario != null) {
                persistenciaService.delete(muebleInventario);
            }
        } catch (Exception e) {
            throw new TiendaException("Se presentó un error eliminando el inventario del mueble");
        }
    }


    /**
     * Método que permite agregar un mueble en el sistema
     * @param mueble Mueble que será agregado
     */
    @RolesAllowed({"Administrador"})
    public void insertarProducto(Mueble mueble) {
        try {
            if (mueble != null) {
                MuebleInventario muebleInventario = new MuebleInventario();
                muebleInventario.setMueble(mueble);
                muebleInventario.setCantidad(new Integer(1));
                muebleInventario.setPrecio(new Double(0));
                persistenciaService.create(mueble);
                persistenciaService.create(muebleInventario);
            }
        } catch (Exception e) {
            throw new TiendaException("Se presentó un error agregando el mueble");
        }
    }

    /**
     * Método que pemite editar el inventario de productos en el sistema
     * @param muebleInventario Mueble con los datos que serán actualizados
     */
    public void editarProductoInventario(MuebleInventario muebleInventario) {

        try {
            if (muebleInventario != null) {
                persistenciaService.update(muebleInventario);
            }
        } catch (Exception e) {
            throw new TiendaException("No fué posible actualizar el inventario del mueble");
        }
    }

    /**
     * Método que permite editar un mueble en el sistema
     * @param mueble  Mueble con los datos con los cuales será actualizado
     */
    @RolesAllowed({"Administrador"})
    public void editarProducto(Mueble mueble) {
        try {
            if (mueble != null) {
                persistenciaService.update(mueble);
            }
        } catch (Exception e) {
            throw new TiendaException("No fué posible actualizar el mueble");
        }
    }

    /**
     * Método que permite consultar el inventario de un mueble
     * @param mueble Mueble del cuál se quiere consultar el inventario
     * @return MuebleInventario retorna el inventario de un mueble
     */
    public MuebleInventario consultarMuebleInventarioPorMueble(Mueble mueble) {

        Query query = null;
        String queryText = "SELECT o FROM MuebleInventario o WHERE o.mueble.referencia = :ref";
        MuebleInventario muebleInventario = new MuebleInventario();

        try {
            query = em.createQuery(queryText);
            query.setParameter("ref", mueble.getReferencia());
            muebleInventario = (MuebleInventario) query.getSingleResult();
        } catch (NoResultException e) {
            e.printStackTrace();
        } catch (NonUniqueResultException e) {
            e.printStackTrace();
        }
        return muebleInventario;
    }

    /**
     * Método que permite consultar un mueble por la llave primaria, por la
     * referencia
     * @param mueble Mueble que se desea buscar, con la referencia
     * @return Retorna el mueble asociado a la referencia ingresada
     */
    public Mueble consultarMueblePorId(Mueble mueble) {
        Mueble m = null;
        Mueble muebleTemp = new Mueble();
        try {
            if (mueble != null) {
                m = (Mueble)persistenciaService.findById(Mueble.class, mueble.getReferencia());
                if(m != null)
                    muebleTemp = (Mueble)m.clone();
                else
                    return null;
            }
        } catch (Exception e) {
            Logger.getLogger(ProductoService.class.getName()).log(Level.SEVERE, null, e);
            throw new TiendaException("Se presentó un error consultando el mueble");
        }
        return muebleTemp;
    }
}
